home *** CD-ROM | disk | FTP | other *** search
- /*
- * i o . c -- Low level I/O
- *
- * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
- *
- *
- * Permission to use, copy, and/or distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that both the above copyright notice and this permission notice appear in
- * all copies and derived works. Fees for distribution or use of this
- * software or derived works may only be charged with express written
- * permission of the copyright holder.
- * This software is provided ``as is'' without express or implied warranty.
- *
- * This software is a derivative work of other copyrighted softwares; the
- * copyright notices of these softwares are placed in the file COPYRIGHTS
- *
- * Author: Erick Gallesio [eg@kaolin.unice.fr]
- * Creation date: ????
- * Last file update: 14-Jul-1996 10:44
- */
-
- #ifdef WIN32
- # include <windows.h>
- # include <io.h>
- # include <fcntl.h>
- #endif
-
- #include "stk.h"
- #include "sport.h"
-
- #define BUFFER_SIZE 512
- #define SYSTEM(instr) { instr; }
- #define STRING_PORTP(f) (((struct str_iob *) f)->signature == SPORT_SIGNATURE)
-
- #ifdef WIN32
- FILE * STk_stdin, *STk_stdout, *STk_stderr;
- #endif
-
- static char buffer[BUFFER_SIZE+1];
- static int bufidx=0;
- static int count=-1;
- static int previous_char;
- static int ungetted = 0;
- static int filled=0;
-
-
- static void badport(int read)
- {
- Err(read ? "String port is not open for reading"
- : "String port is not open for writing",
- NIL);
- }
-
- #ifdef WIN32
- static DWORD Kbd_Thread(LPDWORD dumb)
- {
- unsigned long size;
-
- for ( ; ; ) {
- ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, BUFFER_SIZE, &size, NULL);
- buffer[size] = '\0';
- count = (int) size;
- filled = 1;
- }
- /* Never readched */
- return 0;
- }
- #endif
-
- void STk_StdinProc()
- {
- for ( ; ; ) {
- SYSTEM(count = read(fileno(STk_stdin), buffer, BUFFER_SIZE););
- if (count != -1 || errno != EINTR) break;
- }
- filled = 1;
- }
-
- int STk_getc(FILE *f)
- {
- if (f == STk_stdin) {
- if (ungetted) {
- ungetted = 0;
- return previous_char;
- }
- if (bufidx < count) return buffer[bufidx++];
- else {
- #ifdef USE_TK
- if (Tk_initialized) {
- filled = 0;
- while (!filled) {
- Tcl_DoOneEvent(TK_DONT_WAIT);
- if (Tk_GetNumMainWindows() <= 0) return EOF;
- }
- }
- # ifndef WIN32
- else
- STk_StdinProc();
- # endif
- #else
- /* This code is for snow only (Unix and Win32 flavours) */
- STk_StdinProc();
- #endif
- if (count <= 0) return EOF;
- else {
- bufidx = 1;
- return *buffer;
- }
- }
- }
- else
- if (STRING_PORTP(f)) {
- register struct str_iob *g = (struct str_iob *)f;
- if (!(g->flag & READING)) badport(TRUE);
- return (--(g->cnt)>=0? ((int)*g->ptr++): EOF);
- }
- else {
- int result;
- SYSTEM(result=getc(f));
- return result;
- }
- }
-
- int STk_ungetc(int c, FILE *f)
- {
- if (f == STk_stdin) {
- ungetted = 1;
- previous_char = c;
- }
- else
- if (STRING_PORTP(f)) {
- register struct str_iob *g = (struct str_iob *)f;
- if (g->ptr == g->base) Err("INTERNAL ERROR: cannont unget char", NIL);
- if (!(g->flag & READING)) badport(TRUE);
- g->ptr--;
- g->cnt++;
- }
- else
- SYSTEM(ungetc(c, f));
- return c;
- }
-
- int STk_putc(int c, FILE *f)
- {
- if (STRING_PORTP(f)) {
- register struct str_iob *g = (struct str_iob *)f;
- register int tmp;
-
- if (!(g->flag & WRITING)) badport(FALSE);
- if (++g->cnt == g->bufsiz) {
- tmp = g->bufsiz;
- tmp += tmp/2;
- g->base = must_realloc(g->base, tmp);
- g->ptr = g->base + g->bufsiz - 1; /* since base can have been moved */
- g->bufsiz = tmp;
- }
- *g->ptr++ = (char) c;
- }
- else {
- SYSTEM(c=fputc(c, f));
- /* Signal an error if write fails. We can't be very cute here */
- if (c == EOF) Err("write-char: write error", NIL);
- }
- return c;
- }
-
- int STk_puts(char *s, FILE *f)
- {
- if (STRING_PORTP(f)) {
- while (*s) STk_putc(*s++, f);
- return 0;
- }
- else {
- int result;
- SYSTEM(result = fputs(s, f));
- if (result == EOF) Err("write: write-error", NIL);
- return result;
- }
- }
-
- int STk_eof(FILE *f)
- {
- if (STRING_PORTP(f))
- return (((struct str_iob *)f)->cnt <= 0);
- else {
- int result;
- SYSTEM(result=feof(f));
- return result;
- }
- }
-
-
- char * STk_line_bufferize_io(FILE *f)
- {
- char *buff;
-
- if ((buff=malloc(BUFFER_SIZE)) == NULL)
- panic("Cannot allocate a line buffer for output file");
- setvbuf(f, buff, _IOLBF, BUFFER_SIZE);
- return buff;
- }
-
-
- #ifdef WIN32
- /*
- * Windows apps don't have an associated console. The following code
- * associate a console to the 3 standard files. However, for some
- * reason, even when closing stdin stdout and stderr, I was not able
- * to remap console files on the first enties. Hence, the file name
- * change from stdin to STk_stdin ...
- */
- # include <windows.h>
- # include <io.h>
- # include <fcntl.h>
-
-
- void STk_init_io(void)
- {
- HANDLE Fin, Fout, Ferr;
- unsigned long dumb;
-
- if (AllocConsole()) {
- Fin = GetStdHandle(STD_INPUT_HANDLE);
- Fout = GetStdHandle(STD_OUTPUT_HANDLE);
- Ferr = GetStdHandle(STD_ERROR_HANDLE);
-
- fclose(stdin); fclose(stdout); fclose (stderr);
-
- STk_stdin = fdopen(_open_osfhandle((long) Fin, O_RDONLY), "r");
- STk_stdout = fdopen(_open_osfhandle((long) Fout, O_APPEND), "w");
- STk_stderr = fdopen(_open_osfhandle((long) Ferr, O_APPEND), "w");
-
- fflush(STk_stdout);
- SetConsoleTitle(" *** STk console *** ");
-
- /* Create a thread for reading keyboard */
- #ifdef USE_TK
- CreateThread(NULL, 100, (LPTHREAD_START_ROUTINE) Kbd_Thread, NULL, 0, &dumb);
- #endif
- }
- else
- STk_panic("Cannot create Win32 console");
- }
- #endif
-